<?php

namespace app\command;

use app\helper\ProcessLockHelper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use app\api\QbApi;
use app\api\TrApi;
use app\model\Download;
use app\model\TorrentBank;
use app\model\SystemLog;
use Rhilip\Bencode\Bencode;
use Rhilip\Bencode\ParseException;


class TaskPieceshash1 extends Command
{
    protected static $defaultName = 'task:pieceshash';
    protected static $defaultDescription = '计算种子pieces_hash任务';

    /**
     * @return void
     */
    protected function configure()
    {
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // // 初始化两个任务锁
        $piecesHashLock = new ProcessLockHelper(1);
        $reseedLock = new ProcessLockHelper(2);
        // // 判断任务锁是否存在
        if ($piecesHashLock->isLockExists() || $reseedLock->isLockExists()) {
            // SystemLog::create(['type'=>'error','msg'=> '计划任务执行中，暂不执行种子库更新【如果一直这样显示，请点击清理任务锁】']);
            return 0;
        }
        if (count(Download::select()) == 0) {
            // SystemLog::create(['type'=>'error','msg'=> '下载器暂未配置，无法更新种子库']);
            return 0;
        }
        // 创建任务锁
        $piecesHashLock->createLock();
        // 开始时间计时
        $start_time = microtime(true);
        // 种子库插入数组
        $saveArray = [];
        // 下载器循环
        foreach (Download::where('status',1)->select() as $download) {
            // SystemLog::create(['type'=>'info','msg'=> '正在执行下载器' . $download['name'] . '种子库计算任务']);
            // 获取下载器中种子目录
            $save_path = $download['save_path'];
            // 种子目录判定是否存在
            if (!is_dir($save_path)) {
                // SystemLog::create(['type'=>'error','msg'=> "非文件夹或不存在, 请检查[种子目录]映射是否正确"]);
                // 跳过当前下载配置，继续下一个
                continue;
            }
            // 初始化种子库模型
            $download_bank = TorrentBank::where("download_id",$download['id'])->select();
            // 首先判断种子库数据库中有记录
            if (count($download_bank) > 0) {
                foreach ($download_bank as $key => $value) {
                    // 拼接种子地址
                    $file_name = $save_path . DIRECTORY_SEPARATOR . $value['info_hash'] . ".torrent";
                    // 如果种子不存在了，则同步删除种子库对应数据
                    if (!file_exists($file_name)) {
                        TorrentBank::where('info_hash', $value['info_hash'])->delete();
                    }
                }
            }
            if ($download['type'] == 1) {
                $api = new QbApi($download);
                $result = $api->getTorrentsInfo('', 'completed');

            } else {
                $api = new TrApi($download);
                $result = $api->getTorrentsInfo();
                $result = $result['arguments']['torrents'];
            }
            if($api->login_status == 0) {
                $download->status = 0;
                $download->save();
                // SystemLog::create(['type'=>'error','msg'=> "下载器:".$download->name."连接失败,请检查配置，跳过该下载器的种子库计算并将下载器状态改为关闭"]);
                continue;
            }
            // SystemLog::create(['type'=>'info','msg'=> "通过下载器API发现" . count($result) . "个种子"]);
            $torrentFiles = glob($save_path . '/*.torrent');
            foreach ($torrentFiles as $file_path) {
                if (filesize($file_path) > 5 * 1024 * 1024) {
                    // SystemLog::create(['type'=>'error','msg'=> "种子文件大于5M，不执行辅种任务，种子目录：" . $file_path]);
                    continue;
                }
                try {
                    $torrent_data = file_get_contents($file_path);
                    $torrent = Bencode::decode($torrent_data);
                } catch (ParseException $e) {
                    // SystemLog::create(['type'=>'success','msg'=> $e->getMessage()]);
                    continue;
                }
                $info = $torrent['info'];
                $pieces = $info['pieces'];
                $info_hash = sha1(Bencode::encode($info));
                $pieces_hash = sha1($pieces);
                $flag = self::isHashFound($result, $info_hash, $download['type']);
                if ($flag) {
                    array_push($saveArray, [
                        'info_hash' => $info_hash,
                        'pieces_hash' => $pieces_hash,
                        'save_path' => $download['type'] == 1 ? $result[$flag]['save_path'] : $result[$flag]['downloadDir'],
                        'download_id' => $download['id'],
                    ]);
                }
            }
        }
        try {
            $saveArray = self::arrayUnique($saveArray);
            // $bank = new TorrentBank();
            // $bank->replace()->saveAll($saveArray);
        } catch (\Exception $e) {
            // SystemLog::create(['type'=>'error','msg'=> '种子计算任务失败！']);
            $piecesHashLock->removeLock();
            throw new \Exception($e->getMessage());
        }
        $end_time = microtime(true);
        $execution_time = number_format((float) ($end_time - $start_time), 2);
        // SystemLog::create(['type'=>'info','msg'=> '种子计算任务已完成']);
        $piecesHashLock->removeLock();
        return 1;
    }

    // 判断种子文件是否在下载器中
    private function isHashFound($array = [], $hash = '', $type = 1)
    {
        $found = false;
        if ($type == 1) {
            $hashname = 'hash';
        } else {
            $hashname = 'hashString';
        }
        foreach ($array as $key => $item) {
            if (isset($item[$hashname]) && $item[$hashname] === $hash) {
                $found = $key;
                break;
            }
        }
        return $found;
    }

    /**
     * 数组去重函数
     */
    private function arrayUnique($array = [])
    {
        $uniqueArray = [];
        foreach ($array as $item) {
            $key = $item['pieces_hash'] . '_' . $item['download_id'];
            // 检查这个组合是否已经存在于 $uniqueArray 中    
            if (!isset($uniqueArray[$key])) {
                $uniqueArray[$key] = $item;
            }
            $keys = array_keys($uniqueArray);
            $flippedArray = array_intersect_key($uniqueArray, $keys);
        }
        return $uniqueArray;
    }
}
